﻿/*using Newtonsoft.Json.Linq;
using SmartWeighMonitor.Model;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ZXing;
using ZXing.Common;
using ZXing.QrCode.Internal;
using SmartWeighMonitor;
using SmartWeigh;
using Newtonsoft.Json;
using OfficeOpenXml;

namespace SmartWeighMonitor.Utils
{
    public class PrintUtils
    {
        SynchronizationContext _syncContext = SynchronizationContext.Current;
        static string status = "";
        static string fileName = "";
        static string position = "";

        public static void printWeighOrder(Bill billModel,string positionCode)
        {
            position = positionCode;
            findBillLog(billModel.orderCode);

            if ("1".Equals(status))
            {
                fileName = "tplWeighOrderzg";
            }
            else if ("2".Equals(status))
            {
                fileName = "tplWeighOrderqs";
            }
            else if ("3".Equals(status))
            {
                fileName = "tplWeighOrder";
            }
            else
            {
                fileName = "tplWeighOrder";
            }
            string jmCode = md5(billModel.id);
            doUpdateScreenPicture(billModel.id, billModel.id);
            Bitmap bitmap = Create(billModel.id);
            insertPic();

            doPrint(fileName, billModel);
             status = "";
             fileName = "";
             position = "";
        }

        private static void doPrint(string tplName, Bill billModel)
        {
            Microsoft.Office.Interop.Excel.Application ExcelApp = new Microsoft.Office.Interop.Excel.Application();
            ExcelApp.Visible = false;//是打开可见
            Microsoft.Office.Interop.Excel.Workbooks wbks = ExcelApp.Workbooks;
            Microsoft.Office.Interop.Excel._Workbook wbk = wbks.Add(System.AppDomain.CurrentDomain.BaseDirectory + "/Report/" + tplName + ".xlsx");
            Microsoft.Office.Interop.Excel.Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wbk.Worksheets[1];

            billModel.CurTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

            try
            {
                int rows = ws.UsedRange.Rows.Count;
                int columns = ws.UsedRange.Columns.Count;

                for (int i = 1; i <= rows; i++)
                {
                    for (int j = 1; j <= columns; j++)
                    {
                        if (null != ws.Cells[i, j] && null != ws.Cells[i, j].Value2)
                        {
                            string _val = ws.Cells[i, j].Value2.ToString();
                            if (!_val.StartsWith("${"))
                            {
                                continue;
                            }
                            string fieldName = _val.Substring(2, _val.Length - 3);
                            try
                            {
                                FieldInfo filedInfo = billModel.GetType().GetField(fieldName);
                                if (null != filedInfo.GetValue(billModel))
                                {
                                    ws.Cells[i, j] = filedInfo.GetValue(billModel).ToString();
                                }
                            }
                            catch { }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            string printer1 = App.GetConfig().Printer001;
            string printer2 = App.GetConfig().Printer002;
            if ("001".Equals(position))
            {
                wbk.PrintOutEx(Type.Missing, Type.Missing, Type.Missing, Type.Missing, printer1, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
            }
            else
            {
                wbk.PrintOutEx(Type.Missing, Type.Missing, Type.Missing, Type.Missing, printer2, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
            }
            //wbk.PrintOutEx(1, 1, 1, printerName, false, false, false, false);
            KillProcess(ExcelApp); //杀掉生成的进程
            GC.Collect(); //垃圾回收机制
        }
        [DllImport("User32.dll")]
        public static extern int GetWindowThreadProcessId(IntPtr Hwnd, out int PID);
        private static void KillProcess(Microsoft.Office.Interop.Excel.Application AppObject)
        {
            int Pid = 0;
            IntPtr Hwnd = new IntPtr(AppObject.Hwnd);
            System.Diagnostics.Process p = null;
            try
            {
                GetWindowThreadProcessId(Hwnd, out Pid);
                p = System.Diagnostics.Process.GetProcessById(Pid);
                if (p != null)
                {
                    p.Kill();
                    p.Dispose();
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("进程关闭失败！异常信息：" + ex);
            }
        }
        public static Bitmap Create(string msg)
        {
            MultiFormatWriter writer = new MultiFormatWriter();
            Dictionary<EncodeHintType, object> hint = new Dictionary<EncodeHintType, object>();
            //设置二维码为utf-8编码
            hint.Add(EncodeHintType.CHARACTER_SET, "utf-8");
            //设置纠错等级， 高
            hint.Add(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            BitMatrix bm = writer.encode(msg, BarcodeFormat.QR_CODE, 200, 120, hint);
            BarcodeWriter barcodeWriter = new BarcodeWriter();
            //{
            //    Format = BarcodeFormat.QR_CODE,
            //    Options = new ZXing.Common.EncodingOptions
            //    {
            //        Margin = 0, // 设置二维码边距为0，即去除白框
            //        Width = 300, // 设置二维码图片宽度
            //        Height = 300 // 设置二维码图片高度 }
            //    }
            //};
            Bitmap bitmap = barcodeWriter.Write(bm);
            string codePath = Directory.GetCurrentDirectory() + "/code.jpg";
            if (File.Exists(codePath))
                File.Delete(codePath);
            bitmap.Save(codePath);
            return bitmap;
        }

        public static string md5(string input)
        {
            // Use input string to calculate MD5 hash
            MD5 md5 = System.Security.Cryptography.MD5.Create();
            byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
            byte[] hashBytes = md5.ComputeHash(inputBytes);

            // Convert the byte array to hexadecimal string
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hashBytes.Length; i++)
            {
                sb.Append(hashBytes[i].ToString("X2"));
                // To force the hex string to lower-case letters instead of upper-case, use he
                // following line instead: sb.Append(hashBytes[i].ToString("x2"));
            }
            return sb.ToString();
        }
        public static void insertPic()
        {
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
            ExcelPackage excel = new ExcelPackage(new FileInfo(System.AppDomain.CurrentDomain.BaseDirectory + "/Report/" + fileName + ".xlsx"));
            var ws = excel.Workbook.Worksheets[0];
            FileInfo imageFile = new FileInfo(System.AppDomain.CurrentDomain.BaseDirectory + "/code.jpg");
            var picture = ws.Drawings.AddPicture(DateTime.Now.ToString("yyyyMMddHHmmss"), imageFile);
            if ("tplWeighOrderqs".Equals(fileName))
            {
                picture.SetPosition(310, 105);
                picture.SetSize(130, 85);
            }
            else
            {
                picture.SetPosition(245, 105);
                picture.SetSize(130, 85);
            }

            //picture.SetPosition(430, 50);
            //picture.SetSize(180, 120);
            excel.SaveAs(new FileInfo(System.AppDomain.CurrentDomain.BaseDirectory + "/Report/" + fileName + ".xlsx"));
        }
        public static void doUpdateScreenPicture(String encryptionNumber, String id)
        {
            JObject paramObject = new JObject();
            paramObject.Add("encryptionNumber", encryptionNumber);
            paramObject.Add("id", id);

            try
            {
                String serverIp = App.GetConfig().HttpServerIp;
                String serverPort = App.GetConfig().HttpServerPort;
                String response = HttpPostHelper.doHttpPost("http://" + serverIp + ":" + serverPort + "/qd-s-purchase/purchaseBill/updateBillWeightPicture", paramObject.ToString());
                JObject rspJson = JObject.Parse(response);
                string code = rspJson["code"].ToString();
                if (code.ToLower() == "00000")
                {
                }
            }
            catch (Exception ex) { }
        }

        public static void findBillLog(String billNo)
        {
            JObject paramObject = new JObject();
            paramObject.Add("billNo", billNo);
            List<string> statusList = new List<string>();
            List<string> coldStatusList = new List<string>();
            try
            {
                String serverIp = App.GetConfig().HttpServerIp;
                String serverPort = App.GetConfig().HttpServerPort;
                String response = HttpPostHelper.doHttpPost("http://" + serverIp + ":" + serverPort + "/qd-s-factory/clientApi/findBillLogList", paramObject.ToString());
                JObject rspJson = JObject.Parse(response);
                string code = rspJson["code"].ToString();
                {
                    var jsonStr = rspJson["data"].ToString();
                    List<BillLog> bills = JsonConvert.DeserializeObject<List<BillLog>>(jsonStr);

                    foreach (BillLog billLog in bills)
                    {
                        statusList.Add(billLog.status);
                        coldStatusList.Add(billLog.coldStatus);
                    }
                    if (statusList.Contains("41"))
                    {
                        status = "1";
                    }
                    else if (statusList.Contains("511"))
                    {
                        status = "2";
                    }
                    else if (coldStatusList.Contains("3"))
                    {
                        status = "3";
                    }
                    else if (coldStatusList.Contains("2"))
                    {
                        status = "4";
                    }
                    else if (coldStatusList.Contains("2") && statusList.Contains("511"))
                    {
                        status = "5";
                    }
                    else {
                        status = "6";
                    }
                }
            }
            catch (Exception ex) { }
        }

        //private void SetDataList(object obj)
        //{
        //    List<string> statusList = new List<string>();
        //    if (null == obj) return;
        //    List<BillLog> bills = (List<BillLog>)obj;
        //    foreach (BillLog billLog in bills)
        //    {
        //        statusList.Add(billLog.status);
        //    }
        //    if (statusList.Contains("41"))
        //    {
        //        status = "1";
        //    }else if (statusList.Contains("511"))
        //    {
        //        status = "2";
        //    }else if (statusList.Contains("521"))
        //    {
        //        status = "3";
        //    }
        //}
    }
}
*/

using Newtonsoft.Json.Linq;
using SmartWeighMonitor.Model;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using ZXing;
using ZXing.Common;
using ZXing.QrCode.Internal;
using OfficeOpenXml;
using Excel = Microsoft.Office.Interop.Excel;
using SmartWeigh;

namespace SmartWeighMonitor.Utils
{
    public class PrintUtils
    {
        private static string status = "";
        private static string fileName = "";
        private static string position = "";

        /// <summary>
        /// 对外主入口：状态→模板→复制到工作副本→插二维码→填充占位符→打印
        /// </summary>
        public static void printWeighOrder(Bill billModel, string positionCode)
        {
            position = positionCode;
            findBillLog(billModel.orderCode);

            // 按你的原逻辑选择模板
            if ("1".Equals(status)) fileName = "tplWeighOrderzg";
            else if ("2".Equals(status)) fileName = "tplWeighOrderqs";
            else if ("3".Equals(status)) fileName = "tplWeighOrder";
            else fileName = "tplWeighOrder";

            // 生成二维码图片 ./code.jpg
            string jmCode = md5(billModel.id);
            doUpdateScreenPicture(billModel.id, billModel.id);
            Bitmap bitmap = Create(billModel.id);

            // 复制模板到工作副本（关键：复制后清只读）
            var workPath = PrepareWorkFile(fileName);

            // 向工作副本插入二维码（插入前再保险清只读）
            InsertQrToWorkFile(
                workPath,
                Path.Combine(Directory.GetCurrentDirectory(), "code.jpg"),
                fileName == "tplWeighOrderqs"
            );

            // 填充占位符并打印
            PrintAndFill(workPath, billModel, position);

            // 打印后可删除工作文件
            try { File.Delete(workPath); } catch { }

            // 清理状态
            status = "";
            fileName = "";
            position = "";
        }

        // =====================================================================
        // ================      目录与工作文件（关键改造） ================

        /// <summary>
        /// 从 /Report 复制模板到 /ReportWork 并返回副本路径； 复制后立刻清除只读属性，保证副本可写。
        /// </summary>
        private static string PrepareWorkFile(string tplName)
        {
            var baseDir = AppDomain.CurrentDomain.BaseDirectory;
            var tplDir = Path.Combine(baseDir, "Report");     // 模板目录（只读管理）
            var workDir = Path.Combine(baseDir, "ReportWork"); // 工作文件目录

            Directory.CreateDirectory(tplDir);
            Directory.CreateDirectory(workDir);

            var tplPath = Path.Combine(tplDir, tplName + ".xlsx");
            if (!File.Exists(tplPath))
                throw new FileNotFoundException("未找到打印模板，请放入 /Report：" + tplPath, tplPath);

            var workPath = Path.Combine(workDir, tplName + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".xlsx");

            // 若残留旧文件，先删
            try
            {
                if (File.Exists(workPath))
                {
                    // 清只读后再删
                    var attr = File.GetAttributes(workPath);
                    if ((attr & FileAttributes.ReadOnly) != 0)
                        File.SetAttributes(workPath, FileAttributes.Normal);
                    File.Delete(workPath);
                }
            }
            catch { }

            // 复制模板到工作副本
            File.Copy(tplPath, workPath, true);

            // 复制会继承只读；立刻去掉只读，确保 EPPlus 能保存
            try
            {
                var wfi = new FileInfo(workPath);
                if (wfi.IsReadOnly) wfi.IsReadOnly = false;
                File.SetAttributes(workPath, FileAttributes.Normal);
            }
            catch { }

            return workPath;
        }

        // =====================================================================
        // ================            插图（EPPlus） ================

        /// <summary>
        /// 向工作副本插入二维码图片；保存前确保文件不是只读。
        /// </summary>
        private static void InsertQrToWorkFile(string xlsxPath, string picPath, bool isQs)
        {
            // 再保险：若目标仍为只读，清掉
            try
            {
                var attr = File.GetAttributes(xlsxPath);
                if ((attr & FileAttributes.ReadOnly) != 0)
                    File.SetAttributes(xlsxPath, FileAttributes.Normal);
            }
            catch { }

            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
            using (var excel = new ExcelPackage(new FileInfo(xlsxPath)))
            {
                var ws = excel.Workbook.Worksheets[0];

                if (!File.Exists(picPath))
                    throw new FileNotFoundException("二维码图片不存在", picPath);

                var pic = ws.Drawings.AddPicture("qr_" + DateTime.Now.ToString("HHmmssfff"), new FileInfo(picPath));
                if (isQs) { pic.SetPosition(310, 105); pic.SetSize(130, 85); }
                else { pic.SetPosition(245, 105); pic.SetSize(130, 85); }

                excel.Save(); // 由于已清只读，这里不会再抛 UnauthorizedAccessException
            }
        }

        // =====================================================================
        // ================    填充占位符 + 打印（Interop） ================

        /// <summary>
        /// 打开工作副本，填充 ${field} 占位符，选择打印机打印，规范释放 COM。
        /// </summary>
        private static void PrintAndFill(string workPath, Bill billModel, string position)
        {
            Excel.Application app = null;
            Excel._Workbook wbk = null;
            Excel.Worksheet ws = null;

            try
            {
                app = new Excel.Application { Visible = false, DisplayAlerts = false };
                wbk = app.Workbooks.Open(workPath, ReadOnly: false);
                ws = (Excel.Worksheet)wbk.Worksheets[1];

                // 时间字段
                billModel.CurTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                // 填充 ${fieldName}
                var used = ws.UsedRange;
                int rows = used.Rows.Count;
                int cols = used.Columns.Count;

                for (int i = 1; i <= rows; i++)
                {
                    for (int j = 1; j <= cols; j++)
                    {
                        var cell = ws.Cells[i, j];
                        if (cell != null && cell.Value2 != null)
                        {
                            string val = cell.Value2.ToString();
                            if (val.Length >= 3 && val.StartsWith("${") && val.EndsWith("}"))
                            {
                                string fieldName = val.Substring(2, val.Length - 3);
                                object repl = TryGetFieldOrProperty(billModel, fieldName);
                                if (repl != null)
                                {
                                    cell.Value2 = repl.ToString();
                                }
                            }
                        }
                    }
                }

                // 打印机
                string printer = ("001".Equals(position)) ? App.GetConfig().Printer001 : App.GetConfig().Printer002;
                if (!string.IsNullOrWhiteSpace(printer))
                    wbk.PrintOutEx(Type.Missing, Type.Missing, Type.Missing, Type.Missing, printer, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                else
                    wbk.PrintOutEx();
            }
            finally
            {
                // 规范释放（不要 Kill 进程）
                try { if (ws != null) Marshal.ReleaseComObject(ws); } catch { }
                try
                {
                    if (wbk != null)
                    {
                        wbk.Close(false);
                        Marshal.ReleaseComObject(wbk);
                    }
                }
                catch { }
                try
                {
                    if (app != null)
                    {
                        app.Quit();
                        Marshal.ReleaseComObject(app);
                    }
                }
                catch { }
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }

        private static object TryGetFieldOrProperty(object obj, string name)
        {
            if (obj == null || string.IsNullOrWhiteSpace(name)) return null;

            var t = obj.GetType();
            var f = t.GetField(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
            if (f != null) return f.GetValue(obj);

            var p = t.GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
            if (p != null) return p.GetValue(obj, null);

            return null;
        }

        // =====================================================================
        // ================        你原来的二维码/工具方法 ================

        public static Bitmap Create(string msg)
        {
            var writer = new MultiFormatWriter();
            var hint = new Dictionary<EncodeHintType, object>
            {
                [EncodeHintType.CHARACTER_SET] = "utf-8",
                [EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.H
            };

            var bm = writer.encode(msg, BarcodeFormat.QR_CODE, 200, 120, hint);
            var barcodeWriter = new BarcodeWriter();
            Bitmap bitmap = barcodeWriter.Write(bm);

            string codePath = Path.Combine(Directory.GetCurrentDirectory(), "code.jpg");
            if (File.Exists(codePath)) File.Delete(codePath);
            bitmap.Save(codePath);
            return bitmap;
        }

        public static string md5(string input)
        {
            using (var md5 = MD5.Create())   // 传统 using 块，兼容 C# 7.3
            {
                byte[] inputBytes = Encoding.ASCII.GetBytes(input);
                byte[] hashBytes = md5.ComputeHash(inputBytes);
                var sb = new StringBuilder();
                for (int i = 0; i < hashBytes.Length; i++)
                    sb.Append(hashBytes[i].ToString("X2"));
                return sb.ToString();
            }
        }

        public static void doUpdateScreenPicture(string encryptionNumber, string id)
        {
            var paramObject = new JObject
            {
                ["encryptionNumber"] = encryptionNumber,
                ["id"] = id
            };

            try
            {
                string serverIp = App.GetConfig().HttpServerIp;
                string serverPort = App.GetConfig().HttpServerPort;
                string url = "http://" + serverIp + ":" + serverPort + "/qd-s-purchase/purchaseBill/updateBillWeightPicture";
                HttpPostHelper.doHttpPost(url, paramObject.ToString());
            }
            catch { }
        }

        public static void findBillLog(string billNo)
        {
            var paramObject = new JObject { ["billNo"] = billNo };
            var statusList = new List<string>();
            var coldStatusList = new List<string>();

            try
            {
                string serverIp = App.GetConfig().HttpServerIp;
                string serverPort = App.GetConfig().HttpServerPort;
                string url = "http://" + serverIp + ":" + serverPort + "/qd-s-factory/clientApi/findBillLogList";
                string response = HttpPostHelper.doHttpPost(url, paramObject.ToString());
                var rspJson = JObject.Parse(response);

                var jsonStr = rspJson["data"] == null ? null : rspJson["data"].ToString();
                if (!string.IsNullOrEmpty(jsonStr))
                {
                    var bills = Newtonsoft.Json.JsonConvert.DeserializeObject<List<BillLog>>(jsonStr);
                    foreach (var billLog in bills)
                    {
                        statusList.Add(billLog.status);
                        coldStatusList.Add(billLog.coldStatus);
                    }

                    if (statusList.Contains("41")) status = "1";
                    else if (statusList.Contains("511")) status = "2";
                    else if (coldStatusList.Contains("3")) status = "3";
                    else if (coldStatusList.Contains("2") && statusList.Contains("511")) status = "5";
                    else if (coldStatusList.Contains("2")) status = "4";
                    else status = "6";
                }
            }
            catch { }
        }
    }
}